package cn.com.dhc.danlu.widget.home;

import android.animation.Animator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.text.Editable;
import android.text.Layout;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.StaticLayout;
import android.text.TextPaint;
import android.text.style.AbsoluteSizeSpan;
import android.text.style.ForegroundColorSpan;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.view.WindowManager;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.LinearInterpolator;
import android.widget.ImageView;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import cn.com.dhc.danlu.R;

/**
 * User: Geek_Soledad(wuhaiyang@danlu.com)
 * Date: 2016-08-01
 * Time: 14:05
 * Description: .....
 */
public class RichTextView extends TextView {
    private int mShortHeight = 0;
    private int mLongHeight = 0;

    private int mHightLightColor;
    private int mHightLightSize;

    private int mNormalSize;
    private int mRowSpace;

    /**
     * 动态改变listView中itemview的高度 会导致 listView 刷新每一个条目
     */
    private boolean isCurrentFolding = false;
    private boolean isFold = true;

    public RichTextView (Context context) {
        this (context, null);
    }

    public RichTextView (Context context, AttributeSet attrs) {
        this (context, attrs, 0);
    }

    public RichTextView (Context context, AttributeSet attrs, int defStyleAttr) {
        super (context, attrs, defStyleAttr);

    }

    public void bindAttr (int normalColor, int hightLightColor, int normalSize, int hightLightSize, int rowSpace) {
        setTextColor (normalColor);
        setTextSize (TypedValue.COMPLEX_UNIT_PX, normalSize);
        setLineSpacing (rowSpace, 1);

        mRowSpace = rowSpace;
        mNormalSize = normalSize;
        mHightLightColor = hightLightColor;
        mHightLightSize = hightLightSize;

    }

    public void bindData (List datas, boolean isFold) {
        if (isCurrentFolding) {
            return;
        }
        if (null == datas || datas.isEmpty ()) {
            setVisibility (GONE);
            return;
        }
        this.isFold = isFold;
        setVisibility (VISIBLE);
        bindText (datas);
        Editable editableText = getEditableText ();
        if (null != editableText) {
            editableText.clear ();
        }
        mLongHeight = calculateHeightByStaticLayout (datas);
        if (datas.size () > PromotionsLayout.THRESHOLD_PRO) {
            List tmpDatas = new ArrayList ();
            for (int i = 0; i < PromotionsLayout.THRESHOLD_PRO; i++) {
                tmpDatas.add (datas.get (i));
            }
            mShortHeight = calculateHeightByStaticLayout (tmpDatas);
            if (isFold) {
                setHeight (mShortHeight);
            } else {
                setHeight (mLongHeight);
            }
        } else {
            setHeight (mLongHeight);
        }
    }

    /**
     * 标识不同的文字颜色
     *
     * @param datas
     *         字符串数据源，List 结构
     */
    private void bindText (List datas) {
        StringBuilder sb = new StringBuilder ();
        for (int i = 0; i < datas.size (); i++) {
            sb.append ("●  ").append (datas.get (i));
            if (i != datas.size () - 1) {
                sb.append ("\n");
            }
        }
        setText (hightLightAction (sb.toString ()));
    }

    private int calculateHeightByStaticLayout (List datas) {
        StringBuilder sb = new StringBuilder ();
        for (int i = 0; i < datas.size (); i++) {
            sb.append ("●  ").append (datas.get (i));
            if (i != datas.size () - 1) {
                sb.append ("\n");
            }
        }
        int width = getScreenWidth () - getMarginPlusPadding (); // - padding - margin
        TextView tmpTextView = new TextView (getContext ());
        tmpTextView.setTextSize (TypedValue.COMPLEX_UNIT_PX, mNormalSize);
        SpannableString spannableString = hightLightAction (sb.toString ());
        tmpTextView.setText (spannableString);
        tmpTextView.setPadding (getPaddingLeft (), getPaddingTop (), getPaddingRight (), getPaddingBottom ());
        tmpTextView.setLineSpacing (mRowSpace, 1);
        TextPaint textPaint = tmpTextView.getPaint ();
        StaticLayout staticLayout = new StaticLayout (spannableString, textPaint, width, Layout.Alignment.ALIGN_NORMAL, 1, mRowSpace, false);

        return staticLayout.getHeight ();
    }

    public SpannableString hightLightAction (String string) {
        String res = string.replace ("[", "").replace ("]", "");
        SpannableString s = new SpannableString (string);
        SpannableString s2 = new SpannableString (res);

        String rex = "\\[([^\\[\\]]*)\\]";

        Pattern p = Pattern.compile (rex);
        Matcher m = p.matcher (s);

        int i = 0;
        while (m.find ()) {
            int start = m.start ();
            int end = m.end ();
            int dx = end - start - 2;
            if (i != 0) {
                start = start - i * 2;
            }
            s2.setSpan (new ForegroundColorSpan (mHightLightColor), start, start + dx, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
            s2.setSpan (new AbsoluteSizeSpan (mHightLightSize), start, start + dx, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
            i++;
        }
        return s2;
    }

    public int getScreenWidth () {
        WindowManager wm = (WindowManager) getContext ().getSystemService (Context.WINDOW_SERVICE);
        return wm.getDefaultDisplay ().getWidth ();
    }

    private int getMarginPlusPadding () {
        int total = getPaddingLeft () + getPaddingRight ();
        ViewGroup.LayoutParams layoutParams = getLayoutParams ();
        if (null != layoutParams && layoutParams instanceof ViewGroup.MarginLayoutParams) {
            ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) layoutParams;
            total += params.leftMargin + params.rightMargin;
        }
        return total;
    }

    public void foldAction () {
        isCurrentFolding = true;
        int startHeight = 0;
        int targetHeight = 0;
        if (isFold) {
            startHeight = mShortHeight;
            targetHeight = mLongHeight;
        } else {
            startHeight = mLongHeight;
            targetHeight = mShortHeight;
        }
        this.isFold = !isFold;
        ValueAnimator animator = ValueAnimator.ofInt (startHeight, targetHeight);
        animator.setInterpolator (new LinearInterpolator ());
        animator.addUpdateListener (new ValueAnimator.AnimatorUpdateListener () {
            @Override
            public void onAnimationUpdate (ValueAnimator animation) {
                int animatedValue = (int) animation.getAnimatedValue ();
                setHeight (animatedValue);
            }
        });
        animator.setInterpolator (new AccelerateDecelerateInterpolator ());
        animator.addListener (new Animator.AnimatorListener () {
            @Override
            public void onAnimationStart (Animator animation) {

            }

            @Override
            public void onAnimationEnd (Animator animation) {
                ViewParent viewParent = getParent ();
                //降低耦合度
                if (null != viewParent && viewParent instanceof ViewGroup) {
                    ViewGroup parent = (ViewGroup) viewParent;
                    ImageView iv_fold = (ImageView) parent.findViewById (R.id.iv_fold);
                    if (null != iv_fold) {
                        iv_fold.setImageResource (isFold () ? R.drawable.icon_fold_down : R.drawable.dl_icon_fold_up);
                    }
                }
                isCurrentFolding = false;
            }

            @Override
            public void onAnimationCancel (Animator animation) {

            }

            @Override
            public void onAnimationRepeat (Animator animation) {

            }
        });
        animator.setDuration (300);
        //执行动画之前先清除所有相关动画
        clearAnimation ();
        animator.start ();
    }

    public boolean isFold () {
        return isFold;
    }

    public int dip2px (Context context, float dipValue) {
        final float scale = context.getResources ().getDisplayMetrics ().density;
        return (int) (dipValue * scale + 0.5f);
    }
}